package reesoft.idgenerator.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reesoft.certificate.agent.CertificateAgent;
import reesoft.certificate.entity.SignRequest;
import reesoft.common.code.ErrorCode;
import reesoft.common.controller.BaseController;
import reesoft.common.entity.Result;
import reesoft.common.util.StringUtil;
import reesoft.idgenerator.IdGenerateException;
import reesoft.idgenerator.IdGeneratorErrorCode;
import reesoft.idgenerator.entity.IdRange;
import reesoft.idgenerator.entity.NextBatchIdRequest;
import reesoft.idgenerator.entity.NextIdRequest;
import reesoft.idgenerator.entity.RegisterIdRequest;
import reesoft.idgenerator.service.IdGenerateService;

/**
 * Created by reesoft on 2017-08-31
 */
@RestController
public class IdGenerateServiceController extends BaseController
{
    private static final Logger LOG = LoggerFactory.getLogger(IdGenerateServiceController.class);

    @Autowired
    private IdGenerateService idGenerateService;

    @Autowired
    private CertificateAgent certificateAgent;

    @RequestMapping("register")
    public String register(RegisterIdRequest registerIdRequest)
    {
        LOG.info("Enter register, name:" + registerIdRequest.getName());

        if (StringUtil.isBlank(registerIdRequest.getName()))
        {
            return makeResponse(ErrorCode.INVALID_PARAMETER, "registerResp");
        }

        Result result = verifySignRequest(registerIdRequest);

        if (!result.isSuccess())
        {
            return makeResponse(result, "registerResp");
        }

        try
        {
            idGenerateService.registerId(registerIdRequest.getName());

            LOG.info("{} register ID {}", registerIdRequest.getAppId(), registerIdRequest.getName());

            return makeResponse(ErrorCode.SUCCESS, "registerResp");
        }
        catch (IdGenerateException e)
        {
            LOG.error(e.toString());
            return makeResponse(e, "registerResp");
        }
    }

    @RequestMapping("check")
    public String check(String name)
    {
        LOG.info("Enter check, name:" + name);

        if (StringUtil.isBlank(name))
        {
            return makeResponse(ErrorCode.INVALID_PARAMETER, "checkResp");
        }

        try
        {
            if (idGenerateService.check(name))
            {
                return makeResponse(ErrorCode.SUCCESS, "checkResp");
            }
            else
            {
                return makeResponse(IdGeneratorErrorCode.ID_NOT_REGISTERED, "checkResp");
            }
        }
        catch (IdGenerateException e)
        {
            LOG.error(e.toString());
            return makeResponse(e, "checkResp");
        }
    }

    @RequestMapping("next")
    public String next(NextIdRequest nextIdRequest)
    {
        LOG.info("Enter next, name:" + nextIdRequest.getName());

        if (StringUtil.isBlank(nextIdRequest.getName()))
        {
            return makeResponse(ErrorCode.INVALID_PARAMETER, "nextResp");
        }

        Result result = verifySignRequest(nextIdRequest);

        if (!result.isSuccess())
        {
            return makeResponse(result, "nextResp");
        }

        try
        {
            long nextId = idGenerateService.next(nextIdRequest.getName());

            LOG.info("Assign ID {} to {}", nextId, nextIdRequest.getAppId());

            return makeResponse(new Result<>(ErrorCode.SUCCESS, nextId), "nextResp");
        }
        catch (IdGenerateException e)
        {
            LOG.error(e.toString());
            return makeResponse(e, "nextResp");
        }
    }

    @RequestMapping("nextBatch")
    public String next(NextBatchIdRequest nextBatchIdRequest)
    {
        LOG.info("Enter next, name:{}, amount:{}", nextBatchIdRequest.getName(), nextBatchIdRequest.getAmount());

        if (StringUtil.isBlank(nextBatchIdRequest.getName())
                || nextBatchIdRequest.getAmount() == null)
        {
            return makeResponse(ErrorCode.INVALID_PARAMETER, "nextBatchResp");
        }

        Result result = verifySignRequest(nextBatchIdRequest);

        if (!result.isSuccess())
        {
            return makeResponse(result, "nextBatchResp");
        }

        try
        {
            IdRange idRange = idGenerateService.next(nextBatchIdRequest.getName(), nextBatchIdRequest.getAmount());

            LOG.info("Assign ID:{} range:[{}, {}] to {}", nextBatchIdRequest.getName(), idRange.getStartValue(),
                    idRange.getStartValue() + idRange.getAmount() - 1, nextBatchIdRequest.getAppId());

            return makeResponse(new Result<>(ErrorCode.SUCCESS, idRange), "nextBatchResp");
        }
        catch (IdGenerateException e)
        {
            LOG.error(e.toString());
            return makeResponse(e, "nextBatchResp");
        }
    }

    private Result verifySignRequest(SignRequest signRequest)
    {
        Result result = certificateAgent.verifySignRequest(signRequest);

        if (!result.isSuccess() && signRequest.getSignType().equalsIgnoreCase("MD5"))
        {
            result = certificateAgent.verifySignRequest(signRequest);
        }

        return result;
    }

    private String makeResponse(IdGenerateException e, String command)
    {
        return makeResponse(e.getCode(), e.getMessage(), null, command);
    }
}
